#pragma once
#include <string>

#include <algorithm>
#include <vector>

#include "spackinfo.h"
#include "../parallel/thread.hpp"

namespace umtl
{
	//--------------------------------------------------
	//

	class spack
	{
	public:
		spack(wchar_t const * packName, wchar_t const * password = 0 );
		~spack();

		bool				add( wchar_t const * filename, unsigned char const * data, unsigned int size );
		bool				addFile( wchar_t const * filename );
		SpackInfo const		find( wchar_t const * filename );
		void				del( wchar_t const * filename );
		bool				exportFile( wchar_t const * filename, wchar_t const * exportName = 0 );
		
		#pragma region private

		typedef SpackInfo::istring istring;
		typedef std::map< istring, SpackInfo * > FileMap;
		typedef std::multimap< unsigned int, SpackInfo * > EmptyVolumeMap;
		typedef std::vector< istring > PathList;

	private:
		void				parse_path( wchar_t const * path, spack::PathList & pathList );
		SpackInfo *			find( spack::PathList & pathList );
		void				insert( SpackInfo * info, bool isLoading );
		void				insertNew( FileMap * fileMap, SpackInfo * info );
		void				insertToEnd( FileMap * fileMap, SpackInfo * info );
		void				load();
		void				save();
		void				saveHeaderPos();
		void				clear();
		void				makeCryptKey( wchar_t const * password );

		spack(spack const &other);
		void operator=(spack const & other);
		std::wstring packName_;
		mapped_file mFile_;

		FileMap fileMap_;
		EmptyVolumeMap emptyVolumeMap_;

		unsigned int headerPos_;
		unsigned int volumePos_;
		unsigned int endPos_;

		bool modifiedHeader_;

		char cryptKey_[ 128 ];

		parallel::critical_section ct_;

		#pragma endregion
	};

	//--------------------------------------------------
}